//#########################################################################
//                              WackiEngie
//           Copyright (c) 2014 Marc Wacker. All rights reserved.
//#########################################################################

#pragma once

#include "WeUtilPrerequisites.h"
#include "WeVector2.h"
#include "WeVector3.h"

namespace WackiEngine
{

	template<class T>
	class Vector4 {
	public:
		T	x, y, z, w;

		Vector4(const T x_ = 0, const T y_ = 0, const T z_ = 0, const T w_ = 1) { x = x_; y = y_; z = z_; w = w_; }
		Vector4(const Vector2<T>& v) { x = v.x; y = v.y; z = 0; w = 1; }
		Vector4(const Vector3<T>& v) { x = v.x; y = v.y; z = v.z; w = 1; }
		Vector4(const Vector4& v) { x = v.x; y = v.y; z = v.z; w = v.w; }

		void set(T x_, T y_, T z_, T w_) { x = x_; y = y_; z = z_; w = w_; }

		//compare operators
		bool	operator==	(const Vector4& b) const	{ return x == b.x && y == b.y && z == b.z && w == b.w; }
		bool	operator!=	(const Vector4& b) const	{ return x != b.x || y != b.y || z != b.z || w != b.w; }

		//operators with temp allocation
		Vector4	operator-	(void) const				{ return Vector4(-x, -y, -z, -w); }
		Vector4	operator+	(const Vector4& v) const	{ return Vector4(x + v.x, y + v.y, z + v.z, w + v.w); }
		Vector4	operator-	(const Vector4& v) const	{ return Vector4(x - v.x, y - v.y, z - v.z, w - v.w); }
		T		operator*	(const Vector4& v) const	{ return x*v.x + y*v.y + z*v.z + w*v.w; };  // dot

		Vector4  operator*	(const T s) const			{ return Vector4(x*s, y*s, z*s, w*s); }
		Vector4  operator/	(const T s) const			{ return Vector4(x / s, y / s, z / s, w / s); }
		Vector4	operator&	(const Vector4& v) const	{ return Vector4(x*v.x, y*v.y, z*v.z, w*v.w); }

		friend Vector4   operator *  (T s, const Vector4& v)  { return Vector4(v.x*s, v.y*s, v.z*s, v.w*s); }

		//assign operators
		Vector4&	operator=	(const Vector2<T>& v)	{ x = v.x; y = v.y; z = 0; w = 1;			return *this; }
		Vector4&	operator=	(const Vector3<T>& v)	{ x = v.x; y = v.y; z = v.z; w = 1;			return *this; }
		Vector4&	operator=	(const Vector4& v)		{ x = v.x; y = v.y; z = v.z; w = v.w;		return *this; }
		Vector4&	operator+=	(const Vector4& v)		{ x += v.x; y += v.y; z += v.z; w += v.w;	return *this; }
		Vector4&	operator-=	(const Vector4& v)		{ x -= v.x; y -= v.y; z -= v.z; w -= v.w;	return *this; }
		Vector4&	operator+=	(const T s)				{ x += s; y += s; z += s; w += s;			return *this; }
		Vector4&	operator-=	(const T s)				{ x -= s; y -= s; z -= s; w -= s;			return *this; }
		Vector4&	operator*=	(const T s)				{ x *= s; y *= s; z *= s; w *= s;			return *this; }
		Vector4&	operator/=	(const T s)				{ x /= s; y /= s; z /= s; w /= s;			return *this; }
		Vector4&	operator&=	(const Vector4& v)		{ x *= v.x; y *= v.y; z *= v.z; w *= v.z;	return *this; }

		T			dot(const Vector4& v)				{ return x * v.x + y * v.y + z * v.z + w * v.w; }
		T			lengthSq()							{ return x * x + y * y + z * z + w * w; }
		T			length()							{ return sqrt(lengthSq()); }
		void		normalize()							{ T l = length(); if(l>0) *this /= l; }
		Vector4		normalized()						{ T l = length(); if(l>0) return *this / l; }
	};

	typedef Vector4<float>		Vector4f;
	typedef Vector4<uint32>		Vector4i;
}



